home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************
- Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
- Amsterdam, The Netherlands.
-
- All Rights Reserved
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the names of Stichting Mathematisch
- Centrum or CWI not be used in advertising or publicity pertaining to
- distribution of the software without specific, written prior permission.
-
- STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
- THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
- FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ******************************************************************/
-
- /* rgb objects */
-
- #include "Python.h"
- #include "import.h"
-
- static PyObject *format_rgb, *format_rgb_b2t, *format_rgb_choices;
- static PyObject *format_grey, *format_grey_b2t, *format_xgrey,
- *format_xgrey_b2t, *format_grey_choices;
- static PyObject *format_rgb8, *format_rgb8_b2t, *format_xrgb8,
- *format_xrgb8_b2t, *format_rgb8_choices;
- static PyObject *format_choices;
-
- #define is_4bytefmt(fmt) (fmt==format_rgb||fmt==format_rgb_b2t)
- #define is_alignfmt(fmt) (fmt==format_grey||fmt==format_grey_b2t||\
- fmt==format_rgb8||fmt==format_rgb8_b2t)
- #define is_b2tfmt(fmt) (fmt==format_grey_b2t||fmt==format_xgrey_b2t||\
- fmt==format_rgb8_b2t||fmt==format_xrgb8_b2t||\
- fmt==format_rgb_b2t)
- #define is_ditherfmt(fmt) (fmt==format_rgb8||fmt==format_rgb8_b2t||\
- fmt==format_xrgb8||fmt==format_xrgb8_b2t)
- #define is_greyfmt(fmt) (fmt==format_grey||fmt==format_grey_b2t||\
- fmt==format_xgrey||fmt==format_xgrey_b2t)
-
- typedef struct {
- PyObject_HEAD
- PyObject *dict; /* Attributes dictionary */
- int is_reader; /* TRUE if this is a reader */
- char *filename; /* filename of the image file */
- FILE *filep;
- int width, height;
- int nchannels;
- int rle;
- int colormapID;
- } rgbobject;
-
- static PyObject *errobject;
-
- staticforward PyTypeObject Rgbtype;
-
- #define is_rgbobject(v) ((v)->ob_type == &Rgbtype)
-
- static char doc_rgb[] =
- "This object can be used to read/write RGB image files.\n"
- "The 'width', 'height' and 'format' attributes give info about the\n"
- "image data read (or to be written)";
-
- /* Routine to easily obtain C data from the dict python data */
- int
- rgbselfattr(self, name, fmt, ptr, wanterr)
- rgbobject *self;
- char *name;
- char *fmt;
- void *ptr;
- int wanterr;
- {
- PyObject *obj;
- char errbuf[100];
-
- obj = PyDict_GetItemString(self->dict, name);
- if (obj == NULL) {
- if (wanterr) {
- sprintf(errbuf, "Required attribute '%s' not set", name);
- PyErr_SetString(errobject, errbuf);
- return 0;
- } else {
- PyErr_Clear();
- return 0;
- }
- }
- if (!PyArg_Parse(obj, fmt, ptr)) {
- if (!wanterr)
- PyErr_Clear();
- return 0;
- }
- return 1;
- }
-
- /* Routine to easily insert integer into dictionary */
- rgbsetintattr(self, name, value)
- rgbobject *self;
- char *name;
- int value;
- {
- PyObject *obj;
- int rv;
-
- obj = PyInt_FromLong(value);
- rv = PyDict_SetItemString(self->dict, name, obj);
- Py_DECREF(obj);
- return rv;
- }
-
- static rgbobject *
- newrgbobject()
- {
- rgbobject *xp;
- xp = PyObject_NEW(rgbobject, &Rgbtype);
- if (xp == NULL)
- return NULL;
- xp->dict = PyDict_New();
- xp->filename = NULL;
- xp->filep = NULL;
- return xp;
- }
-
- static int
- RGBreadheader(self)
- rgbobject *self;
- {
- unsigned char header[512];
- int dimension;
-
- /*
- The RGB header looks as follows:
- 2 bytes IRIS image file magic number
- 1 byte storage format
- 1 byte number of bytes per pixel channel
- 2 bytes number of dimensions
- 2 bytes x size in pixels
- 2 bytes y size in pixels
- 2 bytes number of channels
- 4 bytes minimum pixel value
- 4 bytes maximum pixel value
- 4 bytes ignored
- 80 bytes image name
- 4 bytes colormap ID
- 404 bytes ignored
- */
- if (fread(header, 1, 512, self->filep) != 512) {
- PyErr_SetString(errobject, "Truncated RGB file");
- return 0;
- }
- if ((header[0]<<8|header[1]) != 474) {
- PyErr_SetString(errobject, "Not an RGB file");
- return 0;
- }
- self->rle = header[2];
- if (self->rle != 0 && self->rle != 1)
- goto BadRGB;
- if (header[3] != 1) /* only support 1 byte per pixel */
- goto BadRGB;
- dimension = header[4]<<8|header[5];
- if (dimension < 1 || dimension > 3)
- goto BadRGB;
- self->width = header[6]<<8|header[7];
- self->height = header[8]<<8|header[9];
- rgbsetintattr(self, "width", self->width);
- rgbsetintattr(self, "height", self->height);
- self->nchannels = header[10]<<8|header[11];
- if (self->nchannels != 1 && self->nchannels != 3 && self->nchannels != 4)
- goto BadRGB;
- if (dimension == 1) {
- if (self->height != 1 || self->nchannels != 1)
- goto BadRGB;
- } else if (dimension == 2) {
- if (self->nchannels != 1)
- goto BadRGB;
- }
- /*
- self->pinmin = header[12]<<24|header[13]<<16|header[14]<<8|header[15];
- self->pinmax = header[16]<<24|header[17]<<16|header[18]<<8|header[19];
- */
- if (header[20]) {
- PyObject *obj;
- int rv;
- header[99] = 0; /* just to be sure... */
- obj = PyString_FromString((char *)header+20);
- rv = PyDict_SetItemString(self->dict, "name", obj);
- Py_XDECREF(obj);
- }
- self->colormapID = header[104]<<24|header[105]<<16|
- header[106]<<8|header[107];
- if (self->colormapID == 1) {
- if (self->nchannels != 1)
- goto BadRGB;
- PyDict_SetItemString(self->dict, "format", format_rgb8);
- PyDict_SetItemString(self->dict, "format_choices",
- format_rgb8_choices);
- return 1;
- } else if (self->colormapID != 0)
- goto BadRGB;
- if (self->nchannels == 1) {
- PyDict_SetItemString(self->dict, "format", format_grey);
- PyDict_SetItemString(self->dict, "format_choices",
- format_grey_choices);
- } else {
- PyDict_SetItemString(self->dict, "format", format_rgb);
- PyDict_SetItemString(self->dict, "format_choices",
- format_rgb_choices);
- }
- return 1;
-
- BadRGB:
- PyErr_SetString(errobject, "Illegal or unsupported RGB file");
- return 0;
- }
-
- static int
- initrgbreader(self, name)
- rgbobject *self;
- char *name;
- {
- char *name_copy;
-
- if ((name_copy = malloc(strlen(name)+1)) == NULL) {
- PyErr_NoMemory();
- return 0;
- }
- strcpy(name_copy, name);
- self->filename = name_copy;
- self->is_reader = 1;
- self->filep = fopen(name, "rb");
- if (self->filep == NULL) {
- PyErr_SetFromErrno(PyExc_IOError);
- return 0;
- }
- if (!RGBreadheader(self))
- return 0;
- if (PyErr_Occurred())
- return 0;
- return 1;
- }
-
- static int
- initrgbwriter(self, name)
- rgbobject *self;
- char *name;
- {
- char *name_copy;
-
- if ((name_copy = malloc(strlen(name)+1)) == NULL) {
- PyErr_NoMemory();
- return 0;
- }
- strcpy(name_copy, name);
- self->filename = name_copy;
- self->is_reader = 0;
- PyDict_SetItemString(self->dict, "format", format_rgb);
- PyDict_SetItemString(self->dict, "format_choices", format_choices);
- if (PyErr_Occurred())
- return 0;
- return 1;
- }
-
- /* rgb methods */
-
- static void
- rgb_dealloc(xp)
- rgbobject *xp;
- {
- Py_XDECREF(xp->dict);
- if (xp->filename)
- free(xp->filename);
- if (xp->filep)
- fclose(xp->filep);
- PyMem_DEL(xp);
- }
-
- static PyObject *
- RGBreadimage(self, fmt)
- rgbobject *self;
- PyObject *fmt;
- {
- int x, y, z;
- int v;
- PyObject *rv;
- char *ptr;
- int xstride, ystride, zstride;
-
- x = self->width;
- y = self->height;
- z = self->nchannels;
- if (z == 1) {
- if (is_alignfmt(fmt))
- x = (x + 3) & ~3;
- rv = PyString_FromStringAndSize(NULL, x * y);
- if (rv == NULL)
- return NULL;
- ptr = PyString_AS_STRING((PyStringObject *) rv);
- memset(ptr, 0, x * y);
- if (is_b2tfmt(fmt)) {
- ystride = x;
- } else {
- ptr += x * (y - 1);
- ystride = -x;
- }
- ystride -= self->width;
- zstride = 0;
- xstride = 1;
- } else {
- rv = PyString_FromStringAndSize(NULL, x * y * 4);
- if (rv == NULL)
- return NULL;
- ptr = PyString_AS_STRING((PyStringObject *) rv);
- memset(ptr, 0, x * y * 4);
- if (is_b2tfmt(fmt)) {
- ystride = x * 4;
- } else {
- ptr += x * (y - 1) * 4;
- ystride = -x * 4;
- }
- ptr += 3;
- zstride = -ystride * y - 1;
- ystride -= x * 4;
- xstride = 4;
- }
- for (z = self->nchannels; z > 0; z--) {
- for (y = self->height; y > 0; y--) {
- for (x = self->width; x > 0; x--) {
- v = getc(self->filep);
- if (v == EOF) {
- PyErr_SetString(errobject,
- "Truncated RGB file");
- Py_DECREF(rv);
- return NULL;
- }
- *ptr = v;
- ptr += xstride;
- }
- ptr += ystride;
- }
- ptr += zstride;
- }
- return rv;
- }
-
- static int
- readtab(filep, tab, len)
- FILE *filep;
- unsigned long *tab;
- int len;
- {
- int ch;
- unsigned long v;
- int i;
-
- while (--len >= 0) {
- v = 0;
- for (i = 4; i > 0; i--) {
- if ((ch = getc(filep)) == EOF) {
- PyErr_SetString(errobject,
- "Truncated RGB file");
- return 0;
- }
- v = v << 8 | ch;
- }
- *tab++ = v;
- }
- return 1;
- }
-
- static int
- writetab(filep, tab, len)
- FILE *filep;
- unsigned long *tab;
- int len;
- {
- unsigned long v;
- int i;
-
- while (--len >= 0) {
- v = *tab++;
- for (i = 4; i > 0; i--) {
- putc(v >> 24, filep);
- v <<= 8;
- }
- }
- if (ferror(filep))
- return 0;
- return 1;
- }
-
- static int
- compare(p1, p2)
- const void *p1, *p2;
- {
- return ** (const unsigned long **) p1 - ** (const unsigned long **) p2;
- }
-
- static PyObject *
- RGBreadrleimage(self, fmt)
- rgbobject *self;
- PyObject *fmt;
- {
- int tablen = self->height * self->nchannels;
- unsigned long *starttab = malloc(tablen * sizeof(unsigned long));
- unsigned long *lengthtab = malloc(tablen * sizeof(unsigned long));
- unsigned long **sorttab = malloc(tablen * sizeof(unsigned long *));
- unsigned long **sorttab_ptr;
- unsigned long seek_ptr, seek_pos;
- int i, prev_row;
- int width, n, y, z, stride;
- PyObject *rv;
- unsigned char *ptr, *optr, *cptr;
- int reverse;
-
- if (starttab == NULL || lengthtab == NULL || sorttab == NULL) {
- PyErr_NoMemory();
- goto ErrorExit;
- }
- if (!readtab(self->filep, starttab, tablen))
- goto ErrorExit;
- if (!readtab(self->filep, lengthtab, tablen))
- goto ErrorExit;
- for (i = 0; i < tablen; i++)
- sorttab[i] = &starttab[i];
- qsort(sorttab, tablen, sizeof(unsigned long *), compare);
- sorttab_ptr = sorttab;
-
- width = self->width;
- if (self->nchannels == 1) {
- if (is_alignfmt(fmt))
- width = (width + 3) & ~3;
- stride = 1;
- } else {
- stride = 4;
- width *= 4;
- }
- if (!is_b2tfmt(fmt)) {
- /* If height > 1, the following is still != 0, and it
- is very handy to have this number floating around
- when we have to reverse the image. If height == 0
- or 1 it doesn't matter whether we reverse or not */
- reverse = width * (self->height - 1);
- } else
- reverse = 0;
- rv = PyString_FromStringAndSize(NULL, width * self->height);
- if (rv == NULL)
- goto ErrorExit;
- ptr = (unsigned char *)PyString_AS_STRING((PyStringObject *) rv);
- memset(ptr, 0, width * self->height);
-
- prev_row = -1;
- seek_pos = 512 + 2 * tablen * 4;
- while (--tablen >= 0) {
- i = *sorttab_ptr++ - starttab;
- seek_ptr = starttab[i];
- if (seek_ptr == prev_row) {
- /* copy a row */
- if (reverse) {
- cptr = ptr + reverse - y * width;
- optr = ptr + reverse - (i%self->height)*width;
- } else {
- cptr = ptr + y * width;
- optr = ptr + (i % self->height) * width;
- }
- cptr += stride - z - 1;
- optr += stride - (i / self->height) - 1;
- n = self->width;
- while (--n >= 0) {
- *optr = *cptr;
- optr += stride;
- cptr += stride;
- }
- continue;
- }
- if (seek_pos != seek_ptr) {
- while (seek_pos < seek_ptr) {
- if ((n = getc(self->filep)) == EOF)
- goto EOFError;
- seek_pos++;
- }
- if (seek_pos > seek_ptr) {
- PyErr_SetString(errobject, "Bad rle table");
- goto ErrorExit;
- }
- }
- z = i / self->height;
- y = i % self->height;
- if (reverse)
- optr = ptr + reverse - y * width;
- else
- optr = ptr + y * width;
- optr += stride - z - 1;
- for (;;) {
- int pixel, count;
- if ((pixel = getc(self->filep)) == EOF)
- goto EOFError;
- seek_pos++;
- if (!(count = (pixel & 0x7f)))
- break;
- if (pixel & 0x80) {
- while (count--) {
- if ((pixel = getc(self->filep)) == EOF)
- goto EOFError;
- seek_pos++;
- *optr = pixel;
- optr += stride;
- }
- } else {
- if ((pixel = getc(self->filep)) == EOF)
- goto EOFError;
- seek_pos++;
- while (count--) {
- *optr = pixel;
- optr += stride;
- }
- }
- }
- prev_row = seek_ptr;
- }
-
- free(starttab);
- free(lengthtab);
- free(sorttab);
- return rv;
-
- EOFError:
- PyErr_SetString(errobject, "Truncated RGB file");
- ErrorExit:
- if (starttab)
- free(starttab);
- if (lengthtab)
- free(lengthtab);
- if (sorttab)
- free(sorttab);
- return NULL;
- }
-
- static char doc_read[] = "Read the actual image data as a string.";
-
- static PyObject *
- rgb_read(self, args)
- rgbobject *self;
- PyObject *args;
- {
- PyObject *fmt;
-
- if (!PyArg_ParseTuple(args,""))
- return NULL;
- if (!self->is_reader) {
- PyErr_SetString(errobject, "Cannot read() from writer object");
- return NULL;
- }
- /* Get format (and other args), check, read data, return it */
- if (!rgbselfattr(self, "format", "O", &fmt, 1))
- return NULL;
- if (self->nchannels == 1) {
- if (self->colormapID == 0) {
- if (!is_greyfmt(fmt))
- goto illegal_format;
- } else {
- /* self->colormapID == 1 */
- if (!is_ditherfmt(fmt))
- goto illegal_format;
- }
- } else {
- if (!is_4bytefmt(fmt))
- goto illegal_format;
- }
- if (self->rle)
- return RGBreadrleimage(self, fmt);
- else
- return RGBreadimage(self, fmt);
-
- illegal_format:
- PyErr_SetString(errobject, "Illegal format");
- return NULL;
- }
-
- #define putbyte(p,x) ((p)[0]=(x))
- #define putshort(p,x) ((p)[0]=(x)>>8,(p)[1]=(x))
- #define putlong(p,x) ((p)[0]=(x)>>24,(p)[1]=(x)>>16,(p)[2]=(x)>>8,(p)[3]=(x))
-
- static int
- RGBwriteheader(self, fmt)
- rgbobject *self;
- PyObject *fmt;
- {
- char *name;
- char header[512];
-
- memset(header, 0, 512);
- putshort(header+0, 474);
- putbyte(header+2, self->rle);
- putbyte(header+3, 1);
- if (self->nchannels == 1)
- if (self->height == 1)
- putshort(header+4, 1);
- else
- putshort(header+4, 2);
- else
- putshort(header+4, 3);
- putshort(header+6, self->width);
- putshort(header+8, self->height);
- putshort(header+10, self->nchannels);
- putlong(header+12, 0);
- putlong(header+16, 255);
- if (!rgbselfattr(self, "name", "s", &name, 0))
- name = "no name";
- strncpy(header+24, name, 79);
- if (is_ditherfmt(fmt))
- putlong(header+104, 1);
- else
- putlong(header+104, 0);
- if (fwrite(header, 1, 512, self->filep) != 512) {
- PyErr_SetFromErrno(PyExc_IOError);
- return 0;
- }
- return 1;
- }
-
- static PyObject *
- RGBwriteimage(self, fmt, ptr)
- rgbobject *self;
- PyObject *fmt;
- unsigned char *ptr;
- {
- int x, y, z;
- int xstride, ystride, zstride;
-
- x = self->width;
- y = self->height;
- z = self->nchannels;
- if (z == 1) {
- if (is_alignfmt(fmt))
- x = (x + 3) & ~3;
- if (is_b2tfmt(fmt)) {
- ystride = x;
- } else {
- ptr += x * (y - 1);
- ystride = -x;
- }
- ystride -= self->width;
- zstride = 0;
- xstride = 1;
- } else {
- if (is_b2tfmt(fmt)) {
- ystride = x * 4;
- } else {
- ptr += x * (y - 1) * 4;
- ystride = -x * 4;
- }
- ptr += 3;
- zstride = -ystride * y - 1;
- ystride -= x * 4;
- xstride = 4;
- }
- for (z = self->nchannels; z > 0; z--) {
- for (y = self->height; y > 0; y--) {
- for (x = self->width; x > 0; x--) {
- putc(*ptr, self->filep);
- ptr += xstride;
- }
- ptr += ystride;
- }
- ptr += zstride;
- }
-
- fflush(self->filep);
-
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- static int
- compressrow(iptr, rlebuf, length, stride)
- unsigned char *iptr;
- unsigned char *rlebuf;
- int length, stride;
- {
- unsigned char *ibufend = iptr + length * stride;
- unsigned char *optr = rlebuf;
- unsigned char *sptr;
- int stride2 = 2 * stride;
- int count, todo, cc;
-
- while (iptr < ibufend) {
- sptr = iptr;
- iptr += stride2;
- while (iptr < ibufend && (iptr[-stride2] != iptr[-stride] ||
- iptr[-stride] != iptr[0]))
- iptr += stride;
- iptr -= stride2;
- count = (iptr - sptr) / stride;
- while (count) {
- todo = count > 126 ? 126 : count;
- count -= todo;
- *optr++ = 0x80 | todo;
- while (--todo >= 0) {
- *optr++ = *sptr;
- sptr += stride;
- }
- }
- sptr = iptr;
- cc = *iptr;
- iptr += stride;
- while (iptr < ibufend && *iptr == cc)
- iptr += stride;
- count = (iptr - sptr) / stride;
- while (count) {
- todo = count > 126 ? 126 : count;
- count -= todo;
- *optr++ = todo;
- *optr++ = cc;
- }
- }
- *optr++ = 0;
- return optr - rlebuf;
- }
-
- static PyObject *
- RGBwriterleimage(self, fmt, ptr)
- rgbobject *self;
- PyObject *fmt;
- unsigned char *ptr;
- {
- unsigned char *rlebuf;
- unsigned long *starttab, *lengthtab;
- long pos;
- int tablen, rlebuflen, len;
- int i, y, z;
- int xsize, ysize, zsize, xstride, ystride;
-
- xsize = ystride = self->width;
- ysize = self->height;
- zsize = self->nchannels;
- tablen = ysize * zsize;
- rlebuflen = 1.05 * xsize + 10;
- starttab = (unsigned long *) malloc(tablen * sizeof(unsigned long));
- lengthtab = (unsigned long *) malloc(tablen * sizeof(unsigned long));
- rlebuf = (unsigned char *) malloc(rlebuflen);
-
- if (starttab == NULL || lengthtab == NULL || rlebuf == NULL) {
- PyErr_NoMemory();
- goto ErrorExit;
- }
- if (zsize == 1) {
- if (is_alignfmt(fmt))
- ystride = (ystride + 3) & ~3;
- xstride = 1;
- } else {
- xstride = 4;
- ystride *= 4;
- ptr += 3;
- }
- if (!is_b2tfmt(fmt)) {
- ptr += ystride * (ysize - 1);
- ystride = -ystride;
- }
- ystride += zsize;
-
- pos = 512 + 2 * tablen * 4;
- if (fseek(self->filep, pos, SEEK_SET))
- goto WriteError;
- i = 0;
- for (y = ysize; y > 0; y--) {
- for (z = zsize; z > 0; z--) {
- len = compressrow(ptr, rlebuf, xsize, xstride);
- if (len > rlebuflen) {
- PyErr_SetString(errobject,
- "rlebuf is too small - bad poop");
- goto ErrorExit;
- }
- starttab[i] = pos;
- lengthtab[i] = len;
- if (fwrite(rlebuf, 1, len, self->filep) != len)
- goto WriteError;
- pos += len;
- ptr--;
- i += ysize;
- }
- ptr += ystride;
- i += 1 - tablen;
- }
-
- if (fseek(self->filep, 512, SEEK_SET))
- goto WriteError;
- if (!writetab(self->filep, starttab, tablen))
- goto WriteError;
- if (!writetab(self->filep, lengthtab, tablen))
- goto WriteError;
- fseek(self->filep, 0, SEEK_END);
- fflush(self->filep);
-
- free(starttab);
- free(lengthtab);
- free(rlebuf);
-
- Py_INCREF(Py_None);
- return Py_None;
-
- WriteError:
- PyErr_SetString(errobject, "Error writing RGB file");
-
- ErrorExit:
- if (starttab)
- free(starttab);
- if (lengthtab)
- free(lengthtab);
- if (rlebuf)
- free(rlebuf);
- return NULL;
- }
-
-
- static char doc_write[] = "Write the image data.";
-
- static PyObject *
- rgb_write(self, args)
- rgbobject *self;
- PyObject *args;
- {
- unsigned char *data;
- int datalen;
- int i, width;
- PyObject *fmt;
-
- if (!PyArg_ParseTuple(args, "s#", &data, &datalen))
- return NULL;
- if (self->is_reader) {
- PyErr_SetString(errobject, "Cannot write() to reader object");
- return NULL;
- }
- if (!rgbselfattr(self, "width", "i", &self->width, 1) ||
- !rgbselfattr(self, "height", "i", &self->height, 1) ||
- !rgbselfattr(self, "format", "O", &fmt, 1))
- return NULL;
- if (is_4bytefmt(fmt)) {
- if (!rgbselfattr(self, "rgba", "i", &i, 0))
- i = 0;
- if (i)
- self->nchannels = 4;
- else
- self->nchannels = 3;
- self->colormapID = 0;
- i = 4;
- } else {
- self->nchannels = 1;
- if (is_ditherfmt(fmt))
- self->colormapID = 1;
- else
- self->colormapID = 0;
- i = 1;
- }
- width = self->width;
- if (is_alignfmt(fmt))
- width = (width + 3) & ~3;
- if (width * self->height * i != datalen) {
- PyErr_SetString(errobject, "Incorrect datasize");
- return NULL;
- }
- self->filep = fopen(self->filename, "wb");
- if (self->filep == NULL) {
- PyErr_SetFromErrno(PyExc_IOError);
- return NULL;
- }
-
- if (!rgbselfattr(self, "rle", "i", &self->rle, 0))
- self->rle = 1;
-
- if (!RGBwriteheader(self, fmt))
- return NULL;
-
- if (self->rle)
- return RGBwriterleimage(self, fmt, data);
- else
- return RGBwriteimage(self, fmt, data);
- }
-
- static struct PyMethodDef rgb_methods[] = {
- {"read", (PyCFunction)rgb_read, 1, doc_read},
- {"write", (PyCFunction)rgb_write, 1, doc_write},
- {NULL, NULL} /* sentinel */
- };
-
- static PyObject *
- rgb_getattr(xp, name)
- rgbobject *xp;
- char *name;
- {
- PyObject *v;
-
- if (xp->dict != NULL) {
- if (strcmp(name, "__dict__") == 0) {
- Py_INCREF(xp->dict);
- return xp->dict;
- }
- if (strcmp(name, "__doc__") == 0) {
- return PyString_FromString(doc_rgb);
- }
- v = PyDict_GetItemString(xp->dict, name);
- if (v != NULL) {
- Py_INCREF(v);
- return v;
- }
- }
- return Py_FindMethod(rgb_methods, (PyObject *)xp, name);
- }
-
- static int
- rgb_setattr(xp, name, v)
- rgbobject *xp;
- char *name;
- PyObject *v;
- {
- if (xp->dict == NULL) {
- xp->dict = PyDict_New();
- if (xp->dict == NULL)
- return -1;
- }
- if (v == NULL) {
- int rv = PyDict_DelItemString(xp->dict, name);
- if (rv < 0)
- PyErr_SetString(PyExc_AttributeError,
- "delete non-existing imgrgb attribute");
- return rv;
- }
- else
- return PyDict_SetItemString(xp->dict, name, v);
- }
-
- static PyTypeObject Rgbtype = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /*ob_size*/
- "imgrgb", /*tp_name*/
- sizeof(rgbobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)rgb_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- (getattrfunc)rgb_getattr, /*tp_getattr*/
- (setattrfunc)rgb_setattr, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- };
-
- static char doc_newreader[] = "Create reader for file passed as arg.";
-
- static PyObject *
- rgb_newreader(self, args)
- PyObject *self;
- PyObject *args;
- {
- char *filename;
- rgbobject *obj;
-
- if (!PyArg_ParseTuple(args, "s", &filename))
- return NULL;
- if ((obj = newrgbobject()) == NULL)
- return NULL;
- if (!initrgbreader(obj, filename)) {
- rgb_dealloc(obj);
- return NULL;
- }
- return (PyObject *)obj;
- }
-
- static char doc_newwriter[] = "Create writer for file passed as arg.";
-
- static PyObject *
- rgb_newwriter(self, args)
- PyObject *self;
- PyObject *args;
- {
- char *filename;
- rgbobject *obj;
-
- if (!PyArg_ParseTuple(args, "s", &filename))
- return NULL;
- if ((obj = newrgbobject()) == NULL)
- return NULL;
- if (!initrgbwriter(obj, filename)) {
- rgb_dealloc(obj);
- return NULL;
- }
- return (PyObject *)obj;
- }
-
-
- /* List of functions defined in the module */
-
- static struct PyMethodDef rgb_module_methods[] = {
- {"reader", rgb_newreader, 1, doc_newreader},
- {"writer", rgb_newwriter, 1, doc_newwriter},
- {NULL, NULL} /* sentinel */
- };
-
-
- /* Initialization function for the module (*must* be called initimgrgb) */
- static char doc_imgrgb[] = "Module that reads and writes RGB image files.";
-
- void
- initimgsgi()
- {
- PyObject *m, *d, *x, *formatmodule, *formatdict;
-
- /* Create the module and add the functions */
- m = Py_InitModule("imgsgi", rgb_module_methods);
-
- /* Add some symbolic constants to the module */
- d = PyModule_GetDict(m);
- errobject = PyString_FromString("imgsgi.error");
- PyDict_SetItemString(d, "error", errobject);
- x = PyString_FromString(doc_imgrgb);
- PyDict_SetItemString(d, "__doc__", x);
-
- /* Get supported formats */
- if ((formatmodule = PyImport_ImportModule("imgformat")) == NULL)
- Py_FatalError("imgsgi depends on imgformat");
- if ((formatdict = PyModule_GetDict(formatmodule)) == NULL)
- Py_FatalError("imgformat has no dict");
-
- format_rgb = PyDict_GetItemString(formatdict,"rgb");
- format_rgb_b2t = PyDict_GetItemString(formatdict,"rgb_b2t");
- format_rgb_choices = Py_BuildValue("(OO)", format_rgb, format_rgb_b2t);
-
- format_grey = PyDict_GetItemString(formatdict,"grey");
- format_grey_b2t = PyDict_GetItemString(formatdict,"grey_b2t");
- format_xgrey = PyDict_GetItemString(formatdict,"xgrey");
- format_xgrey_b2t = PyDict_GetItemString(formatdict,"xgrey_b2t");
- format_grey_choices = Py_BuildValue("(OOOO)",
- format_grey, format_grey_b2t,
- format_xgrey, format_xgrey_b2t);
-
- format_rgb8 = PyDict_GetItemString(formatdict,"rgb8");
- format_rgb8_b2t = PyDict_GetItemString(formatdict,"rgb8_b2t");
- format_xrgb8 = PyDict_GetItemString(formatdict,"xrgb8");
- format_xrgb8_b2t = PyDict_GetItemString(formatdict,"xrgb8_b2t");
- format_rgb8_choices = Py_BuildValue("(OOOO)",
- format_rgb8, format_rgb8_b2t,
- format_xrgb8, format_xrgb8_b2t);
-
- format_choices = Py_BuildValue("(OOOOOOOOOO)",
- format_rgb, format_rgb_b2t,
- format_grey, format_grey_b2t,
- format_xgrey, format_xgrey_b2t,
- format_rgb8, format_rgb8_b2t,
- format_xrgb8, format_xrgb8_b2t);
-
- /* Check for errors */
- if (PyErr_Occurred())
- Py_FatalError("can't initialize module imgsgi");
- }
-